import { createDecorator } from '../core/helpers'
import { WatchOptions,WatchCallback } from 'vue'

type ObjectWatchOptionItem = {
  handler: WatchCallback | string;
} & WatchOptions;

function create(params:string|string[],wopt:WatchOptions | undefined,target: any, propertyKey: string,descriptor?: PropertyDescriptor){
  createDecorator(function (ctx, key) {
    const options = ctx.options
    if(!options.watch){
      options.watch = {}
    }
    const name = params || key;
    const watch:any = options.watch
    let watchOption:ObjectWatchOptionItem;
    if(wopt){
      watchOption = Object.assign({},wopt,{
        handler: descriptor?.value
      });
    }else{
      watchOption = {
        handler: descriptor?.value
      }
    }
    
    if(Array.isArray(name)){
      name.forEach((item:string)=>{
        watch[item] =  watchOption;
      })
    }else{
      watch[name] =  watchOption;
    }
    ctx.excludeKeys.push(key)

  })(target, propertyKey);
}

export function Watch(params:string|string[],watchOptions?:WatchOptions):any;
export function Watch(target: any, propertyKey: string,descriptor: PropertyDescriptor):void;
export function Watch(target: any, propertyKey:any="",descriptor?: PropertyDescriptor):void | any{
  if(propertyKey && typeof(propertyKey) === 'string'){
    create(propertyKey,undefined, target,propertyKey,descriptor)
  }else{
    const params = target as string | string[];
    const watchOptions = propertyKey as WatchOptions | undefined;
    return function (target: any, propertyKey: string,descriptor: PropertyDescriptor) {
      create(params,watchOptions,target,propertyKey,descriptor)
    };
  }
}
